sitepoint의 Node.js 관련 Article 번역
원문 sitepoint.com의 Web Scraping in Node.js
오역 주의 오역을 발견하시면 꼭 알려주세요~ :-)
웹 스크랩퍼는 프로그래밍된 계획에 따라 웹페이지에 방문하여 데이터를 추출하는 소프트웨어의 일부이다. 웹 스크래핑은 콘텐츠 복제라는 이슈때문에 논란이 많은 주제중 하나이다. 대신에 대부분의 웹사이트 소유자들은 공개된 API를 통해 자신의 데이터에 접근하는 방법을 선호한다. 불행하게도 많은 사이트들은 부실한 API를 제공하거나 그마저도 제공하지 않는다. 이것이 많은 개발자들을 웹 스크래핑에 의지하게 만들었다. 이번 글에서는 Node.js로 여러분들 자신만의 웹 스크래퍼를 구현하는 방법에 대해 알려줄 것이다.
웹 스크래핑의 첫번째 단계는 리모트 서버로부터 소스코드를 다운로드하는 것이다. request 모듈을 사용하여 페이지를 다운로드하는 방법은 “Making HTTP Requests in Node.js”에서 배웠었다. 다음 예제는 Node.js에서 GET
요청 시 빠르게 리프레쉬하게 한다.
var request = require("request");
request({
uri: "http://www.sitepoint.com",
}, function(error, response, body) {
console.log(body);
});
웹 스크래핑의 두번째 단계는 다소 어려운데 그것은 다운로드한 소스코드에서 데이터를 추출하는 것이다. 클라이언트 측에서는 선택자 API나 jQuery같은 라이브러리를 사용하면 별것 아닌 일지만, 아쉽게도 이러한 해결책은 DOM에 쿼리가 가능하다는 사실을 전제로 하고 있다. 안타깝지만 Node.js는 DOM을 제공하지 않는다. 혹시 제공을 하는지?
Node.js가 DOM에 대한 모듈을 내장하고 있지는 않지만, HTML 소스코드의 문자열로부터 DOM을 만들수 있는 여러 모듈이 있다. 그 중 많이 사용하는 두개의 DOM 모듈이 있는데 cheerio와 jsdom이다. 이번 글에서는 cheerio
에 중점을 둘 것이며 다음 명령으로 모듈을 설치할 수 있다.
npm install cheerio
cheerio
모듈은 jQuery의 서브셋(하위집합)을 구현한다. 이것은 많은 개발자들이 빠르게 익힐수 있다는 것을 의미한다. 사실 cheerio
는 jQuery랑 비슷해서 cheerio
에 구현되어 있지 않은 jQuery 함수를 사용하려고 하는 자신을 쉽게 볼 수 있다.
다음 예제는 cheerio
를 사용해서 HTML 문자열을 파싱하는 법을 보여준다. 첫번째 라인에서 cheerio
모듈을 프로그램에 임포트한다. html
변수는 파싱해야할 HTML의 일부분을 가지고 있다. 3 라인에서 그 HTML은 cheerio
모듈을 사용해서 파싱된다. 그 결과를 $
변수에 할당한다. 달러 표시는 jQuery에서 전통적으로 사용되기 때문에 선택했다. 4 라인에서 CSS 스타일의 선택자를 사용해서 <ul>
요소를 선택한다. 마지막으로 html()
메소드를 사용해서 list의 내부 HTML을 출력했다.
var cheerio = require("cheerio");
var html = "<ul><li>foo</li><li>bar</li></ul>";
var $ = cheerio.load(html);
var list = $("ul");
console.log(list.html());
cheerio
는 활발히 개발중에 있고 항상 더 나아지고 있다. 하지만, 여전히 많은 제한사항을 가지고 있다. cheerio
의 가장 불만스러운 점은 HTML 파서이다. HTML 파싱은 어려운 문제이고 잘못된 HTML을 포함한 많은 페이지가 있다. cheerio
모듈이 이러한 페이지들에서 충돌이 발생하지는 않더라도 여러분은 요소를 선택할 수 없게 될지도 모른다. 이것은 버그가 선택자에서 발생하는 것인지 아니면 페이지 자체에서 발생하는 것인지 결정하기 어렵게 만들수 있다.
다음은 완벽한 웹 스크랩퍼를 만들기 위해 request
와 cheerio
모듈을 결합한 예제이다. 예제의 스크랩퍼는 sitepoint 홈페이지에 있는 모든 글들의 제목과 URL을 추출한다. 처음 두개의 라인에서 필요한 모듈을 임포트한다. 3 라인부터 5 라인까지 sitepoint 홈페이지의 소스코드를 다운로드한다. 그리고 나서 파싱을 하기 위해 소스를 cheerio
모듈에 전달했다.
var request = require("request");
var cheerio = require("cheerio");
request({
uri: "http://www.sitepoint.com",
}, function(error, response, body) {
var $ = cheerio.load(body);
$(".entry-title > a").each(function() {
var link = $(this);
var text = link.text();
var href = link.attr("href");
console.log(text + " -> " + href);
});
});
sitepoint의 소스코드를 보면 모든 글의 제목이 entry-title
라는 클래스를 가진 <h1>
요소에 포함된 링크라는 것을 주의해야 할 것이다. 7 라인의 선택자는 모든 글의 링크를 선택한다. 그 다음 each()
함수는 모든 글들을 대상으로 반복하기 위해 사용된다. 마지막으로, 글 제목과 URL은 각각 링크의 텍스트와 href
속성으로부터 얻는다.
이번 글은 Node.js로 간단한 웹 스크래핑 프로그램을 만드는 법을 보여줬다. 이런 방법이 웹 페이지를 스크래핑하는 유일한 방법은 아니다. headless 브라우저(역자주-Graphical User Interface가 없는 웹브라우저)를 사용하는 것과 같은 다른 기술들도 있다. 더 강력하지만, 단순함 및(또는) 속도와 타협을 하게 될지 모른다. 다음 글은 headless 브라우저 모듈 PhantomJS에 대해 중점을 두어 다룰 것이다.